package cn.mujiankeji.mbrowser.界面.标签页.脚本

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import cn.mujiankeji.mbrowser.app.应用接口
import cn.mujiankeji.mbrowser.工具.mlog
import cn.mujiankeji.mbrowser.数据.数据库.AppDatabase
import cn.mujiankeji.mbrowser.数据.数据库.DBUserScript
import cn.mujiankeji.mbrowser.数据.数据库.DaoUserScript
import cn.mujiankeji.mbrowser.界面.框架.主视图.标签页状态
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import org.koin.core.context.GlobalContext
import java.io.File
import java.util.UUID
import kotlinx.datetime.Clock

/**
 * 脚本编辑标签状态
 * 
 * 用于创建或编辑用户脚本
 * 
 * @param 脚本ID 如果是编辑现有脚本，则提供脚本ID；如果是创建新脚本，则为null
 */
class 脚本编辑标签状态(val 脚本ID: Long? = null) : 标签页状态() {
    // 数据库访问对象
    private val dao: DaoUserScript = GlobalContext.get().get<AppDatabase>().用户脚本()
    
    // 脚本数据
    var 脚本 by mutableStateOf(DBUserScript())
    
    // 脚本源代码
    var 脚本源代码 by mutableStateOf("")
    
    // 是否为编辑模式
    val 是否编辑模式 = 脚本ID != null
    
    // 是否正在加载
    var 正在加载 by mutableStateOf(false)
    
    // 是否正在保存
    var 正在保存 by mutableStateOf(false)
    
    // 错误信息
    var 错误信息 by mutableStateOf<String?>(null)
    
    // 协程作用域
    var coroutine: CoroutineScope? = null
    
    // 标题和地址状态流
    override val 标题 = MutableStateFlow<String?>(if (是否编辑模式) "编辑脚本" else "新建脚本")
    override val 地址 = MutableStateFlow<String?>(null)
    override val 加载进度 = MutableStateFlow(100)
    override val 可否后退 = MutableStateFlow(false)
    override val 可否前进 = MutableStateFlow(false)
    
    init {
        if (是否编辑模式) {
            加载脚本()
        } else {
            // 初始化新脚本模板
            初始化新脚本模板()
        }
    }
    
    /**
     * 加载现有脚本
     */
    private fun 加载脚本() {
        正在加载 = true
        错误信息 = null
        
        mlog("开始加载脚本，脚本ID: $脚本ID")
        
        coroutine?.launch {
            try {
                脚本ID?.let { id ->
                    mlog("尝试从数据库加载脚本 ID: $id")
                    val 加载的脚本 = dao.获取用户脚本(id)
                    if (加载的脚本 != null) {
                        mlog("脚本加载成功: ${加载的脚本.名称}")
                        脚本 = 加载的脚本
                        标题.value = "脚本: ${脚本.名称}"
                        
                        // 加载脚本文件内容
                        val 文件路径 = 脚本.获取文件路径()
                        mlog("尝试读取脚本文件: $文件路径")
                        val 文件 = File(文件路径)
                        if (文件.exists()) {
                            脚本源代码 = 文件.readText()
                            mlog("脚本文件内容读取成功，长度: ${脚本源代码.length}")
                        } else {
                            mlog("错误: 脚本文件不存在: $文件路径")
                            错误信息 = "脚本文件不存在: $文件路径"
                        }
                    } else {
                        mlog("错误: 找不到指定的脚本 ID: $id")
                        错误信息 = "找不到指定的脚本 ID: $id"
                    }
                } ?: run {
                    mlog("错误: 脚本ID为空")
                    错误信息 = "脚本ID为空"
                }
            } catch (e: Exception) {
                val 错误消息 = "加载脚本失败: ${e.message}"
                mlog("错误: $错误消息", e)
                错误信息 = 错误消息
                e.printStackTrace()
            } finally {
                mlog("脚本加载过程结束，正在加载: false")
                正在加载 = false
            }
        } ?: run {
            mlog("错误: coroutine为空，无法启动协程")
            错误信息 = "无法启动加载任务，请重试"
            正在加载 = false
        }
    }
    
    /**
     * 初始化新脚本模板
     */
    private fun 初始化新脚本模板() {
        脚本源代码 = """// ==UserScript==
// @name         新脚本
// @namespace    http://mujiankeji.cn/
// @version      0.1
// @description  请在此处添加描述
// @author       您的名字
// @match        https://example.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    
    // 在此处编写您的脚本代码
    console.log('Hello, world!');
})();
"""
    }
    
    /**
     * 保存脚本
     */
    fun 保存脚本() {
        正在保存 = true
        错误信息 = null
        
        coroutine?.launch {
            try {
                // 解析脚本元数据
                val 解析后脚本 = cn.mujiankeji.mbrowser.工具.操作.用户脚本操作.解析(脚本源代码)
                
                // 如果是编辑现有脚本，保留ID和标识符
                if (是否编辑模式 && 脚本ID != null) {
                    解析后脚本.id = 脚本ID
                    解析后脚本.标识符 = 脚本.标识符
                }
                
                // 确保有标识符
                if (解析后脚本.标识符.isEmpty()) {
                    解析后脚本.标识符 = UUID.randomUUID().toString()
                }
                
                // 设置更新时间
                解析后脚本.更新时间 = Clock.System.now().epochSeconds
                
                // 保存脚本内容到文件
                val 文件路径 = 解析后脚本.获取文件路径()
                val 文件 = File(文件路径)
                文件.parentFile?.mkdirs() // 确保目录存在
                文件.writeText(脚本源代码)
                
                // 保存到数据库
                val 新脚本ID = if (是否编辑模式) {
                    dao.更新用户脚本(解析后脚本)
                    解析后脚本.id
                } else {
                    dao.插入用户脚本(解析后脚本)
                }
                
                // 更新状态
                脚本 = 解析后脚本
                标题.value = "脚本: ${脚本.名称}"
                
                // 显示成功消息
                应用接口.输出提示("脚本保存成功")
                
                // 如果是新建脚本，更新当前标签页状态而不是创建新标签页
                if (!是否编辑模式) {
                    // 更新当前标签页的脚本ID，使其变为编辑模式
                    mlog("新脚本已保存，ID: $新脚本ID")
                    // 这里不能直接修改脚本ID，因为它是val，但我们已经更新了脚本对象
                    // 所以现在这个标签页实际上已经变成了编辑模式
                }
            } catch (e: Exception) {
                错误信息 = "保存脚本失败: ${e.message}"
                mlog("保存脚本失败", e)
                应用接口.输出提示("保存脚本失败: ${e.message}")
            } finally {
                正在保存 = false
            }
        }
    }
    
    /**
     * 更新脚本源代码
     */
    fun 更新脚本源代码(新代码: String) {
        脚本源代码 = 新代码
    }
    
    // 标签页接口实现
    override fun 刷新() {
        if (是否编辑模式) {
            加载脚本()
        }
    }
    
    override fun 界面恢复() {
        // 不需要特殊处理
    }
    
    override fun 界面暂停() {
        // 不需要特殊处理
    }
    
    override fun 界面销毁() {
        super.界面销毁()
    }
} 